package com.caiyi.financial.nirvana.sms.gateway.sgip.message;

import com.caiyi.financial.nirvana.sms.gateway.sgip.message.body.*;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;


/**
 * SGIP消息体
 */
public abstract class SGIPBody implements Message {

    private static final Logger logger = LoggerFactory.getLogger(SGIPBody.class);

    //支持的消息类型
    private static Map<Integer, Class<?>> BODY_TYPE = new HashMap();

    //消息类型注册
    static {
        registerBodyType(SGIPMessage.SGIP_BIND, SGIPBind.class);
        registerBodyType(SGIPMessage.SGIP_BIND_RESP, SGIPBindResp.class);
        registerBodyType(SGIPMessage.SGIP_SUBMIT, SGIPSubmit.class);
        registerBodyType(SGIPMessage.SGIP_SUBMIT_RESP, SGIPSubmitResp.class);
        registerBodyType(SGIPMessage.SGIP_DELIVER, SGIPDeliver.class);
        registerBodyType(SGIPMessage.SGIP_DELIVER_RESP, SGIPDeliverResp.class);
        registerBodyType(SGIPMessage.SGIP_REPORT, SGIPReport.class);
        registerBodyType(SGIPMessage.SGIP_REPORT_RESP, SGIPReportResp.class);
        registerBodyType(SGIPMessage.SGIP_UNBIND, SGIPUnbind.class);
        registerBodyType(SGIPMessage.SGIP_UNBIND_RESP, SGIPUnbindResp.class);
    }

    protected final static void registerBodyType(int commandId, Class<?> bodyType) {
        BODY_TYPE.put(commandId, bodyType);
    }

    /***
     * 空消息体
     */
    public static final SGIPBody NOOP_BODY = new NOOPBody();


    /***
     * 消息对象编码到buffer
     * @param buffer
     * @return 编码长度
     */
    public abstract int encode(ByteBuf buffer);


    /***
     * buffer解码成消息对象
     * @param buffer
     * @return
     */
    public abstract SGIPBody decode(ByteBuf buffer);


    /**
     *
     */
    public static SGIPBody decodeBody(int commandId, ByteBuf buffer) {
        SGIPBody body = createBody(commandId);
        body.decode(buffer);
        return body;
    }

    /**
     * 根据消息ID生成消息对象
     *
     * @param commandId
     * @return SGIPBody
     */
    public static SGIPBody createBody(int commandId) {
        SGIPBody body = null;
        try {
            body = SGIPBody.newInstance(commandId);
        } catch (Exception e) {
            logger.warn("createBody error", e);
        }
        return body;
    }


    /**
     * 消息ID对应消息类
     *
     * @param commandId
     * @return
     */
    public final static Class<?> getBodyType(int commandId) {
        return BODY_TYPE.get(commandId);
    }

    /**
     * 消息对象对应的消息ID
     *
     * @param clazz
     * @return
     */
    public final static int getMessageCommandByBodyType(Class<?> clazz) {
        for (Entry<Integer, Class<?>> body : BODY_TYPE.entrySet()) {
            if (body.getValue().equals(clazz))
                return body.getKey();
        }
        throw new IllegalArgumentException("未注册的消息类！");
    }

    /***
     *
     * @param commandId
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static SGIPBody newInstance(int commandId) throws InstantiationException, IllegalAccessException {
        Class<?> type = getBodyType(commandId);
        if (type == null) {
            return new NOOPBody();
        }
        return (SGIPBody) type.newInstance();
    }


    /**
     * 空消息体
     *
     * @author zhu_tek
     */
    public static class NOOPBody extends SGIPBody {
        @Override
        public int encode(ByteBuf buffer) {
            return 0;
        }

        @Override
        public SGIPBody decode(ByteBuf buffer) {
            return this;
        }
    }
}
